/**
 * 
 */
package com.googlecode.jstructs.instr;

import org.objectweb.asm.ClassReader;

import com.googlecode.jstructs.ValueType;

final class ClassTaster {
	static final int CLASS = 7;
	static final int FIELD = 9;
	static final int METH = 10;
	static final int IMETH = 11;
	static final int STR = 8;
	static final int INT = 3;
	static final int FLOAT = 4;
	static final int LONG = 5;
	static final int DOUBLE = 6;
	static final int NAME_TYPE = 12;
	static final int UTF8 = 1;

	static final String VALUETYPE_CNAME = ""
			+ ValueType.class.getName().replace('.', '/');

	String name;
	public boolean isValueType;
	public boolean usesValueType;
	public boolean errSuperIsValueType;

	public boolean isShouldInstrument() {
		return usesValueType || isValueType;
	}

	public void taste(ClassReader cr, ClassLoader loader,
			StructInstrumentation instr) {
		this.name = cr.getClassName();
		String superName = cr.getSuperName();
		this.isValueType = ClassTaster.VALUETYPE_CNAME.equals(superName);
		if (instr.isValueType(loader, superName)) {
			this.errSuperIsValueType = true;
		}
		if (!isValueType) {
			int off = 0;
			int n = cr.readUnsignedShort(off + 8);
			int index = off + 10;
			char[] c = new char[128];
			for1: for (int i = 1; i < n; ++i) {
				int size;
				switch (cr.readByte(index)) {
				case CLASS:
					int item = cr.getItem(cr.readUnsignedShort(index + 1));
					int nsize = cr.readUnsignedShort(item);
					String className = cr.readUTF8(index + 1,
							c.length >= nsize ? c : (c = new char[nsize]));
					if (!name.equals(className)) {
						if (instr.isValueType(loader, className)) {
							usesValueType = true;
							break for1;
						}
					}
					size = 3;
					break;
				case FIELD:
				case METH:
				case IMETH:
				case INT:
				case FLOAT:
				case NAME_TYPE:
					size = 5;
					break;
				case LONG:
				case DOUBLE:
					size = 9;
					++i;
					break;
				case UTF8:
					size = 3 + cr.readUnsignedShort(index + 1);
					break;
				case STR:
				default:
					size = 3;
					break;
				}
				index += size;
			}
		}
	}
}